const Sequelize = require('sequelize');

const Op = Sequelize.Op;
/*const operatorsAliases = {
    $eq: Op.eq,  // 等于
    $ne: Op.ne,  // 不等于
    $gte: Op.gte, // 大于等于
    $gt: Op.gt, // 大于
    $lte: Op.lte,  // 小于等于
    $lt: Op.lt, // 小于
    $not: Op.not,  // 不是
    $in: Op.in,  // 在 [1,2] 只中
    $notIn: Op.notIn, // 不在 [1,2] 只中
    $is: Op.is,  //
    $like: Op.like,    //  如：'%hat' 包含hat
    $notLike: Op.notLike, //  如：'%hat' 不包含hat
    $iLike: Op.iLike,  // 包含 '%hat' (不区分大小写)  (仅限 PG)
    $notILike: Op.notILike,  // 不包含 '%hat' (不区分大小写)  (仅限 PG)
    $regexp: Op.regexp,  // 如： '^[h|a|t]'   匹配正则表达式 (仅限 MySQL/PG)
    $notRegexp: Op.notRegexp,  // 如： '^[h|a|t]'   不匹配正则表达式 (仅限 MySQL/PG)
    $iRegexp: Op.iRegexp,  // ~* '^[h|a|t]' (仅限 PG)
    $notIRegexp: Op.notIRegexp,  // !~* '^[h|a|t]' (仅限 PG)
    $between: Op.between,   // 如：[1,10]  1和10之间
    $notBetween: Op.notBetween,  // 如：[1,10]  不在1和10之间
    $overlap: Op.overlap,  // && [1, 2] (PG数组重叠运算符)
    $contains: Op.contains,  // @> [1, 2] (PG数组包含运算符)
    $contained: Op.contained, // <@ [1, 2] (PG数组包含于运算符)
    $adjacent: Op.adjacent,
    $strictLeft: Op.strictLeft,
    $strictRight: Op.strictRight,
    $noExtendRight: Op.noExtendRight,
    $noExtendLeft: Op.noExtendLeft,
    $and: Op.and,   // 如{a: 5}  且 (a = 5)
    $or: Op.or,   // [{a: 5}, {a: 6}]  // (a = 5 或 a = 6)
    $any: Op.any,   // 任何数组[2, 3]::INTEGER (仅限PG)
    $all: Op.all,
    $values: Op.values,
    $col: Op.col   // 如：'user.organization_id', 使用数据库语言特定的列标识符, 本例使用 PG
};*/

// l建立连接
const sequelize = new Sequelize('test', 'root', '', {
    host: '127.0.0.1',
    dialect: 'mysql',
    // operatorsAliases:false // 不适用
})

// 测试是否连接成功
sequelize.authenticate().then(()=>{
    console.log('连接成功')
}).catch(err => {
    console.error('Unable to connect to the database:', err);
})

// 定义模型
const Users = sequelize.define('Users',{
    id: {
        type: Sequelize.INTEGER(11),
        allowNull:false,
        autoIncrement:true,
        primaryKey: true
    },
    username: {
        type: Sequelize.STRING(50),
        allowNull: false
    },
    age: {
        type: Sequelize.TINYINT,
        allowNull: false
    },
    gender: {
        type: Sequelize.ENUM('0','1','2'),
        allowNull: false
    },
    birthday: {
        type: Sequelize.BIGINT(13)
        // allowNull: false
    },
},{
    timestamps: false,  // 添加时间戳属性 将createdAt和updatedAt时间戳添加到模型中。 http://docs.sequelizejs.com/class/lib/model.js~Model.html#static-method-init
    tableName: 'users' // 隐射的真实表名
})

// 根据主键查找一跳记录
// Users.findByPk(1).then( user => {
//     console.log('username', user.username)
// })

// 查找所有记录
// Users.findAll().then( users => {
//     users.forEach( user => {
//         console.log(user.username)
//     })
// })


// 新增一条记录并保存， 保存完成再次修改 再次保存==
/*let addNewRecord = Users.build({
    username: 'lisi',
    age: 30,
    gender: '1'
})

addNewRecord.save().then( record => {
    // 修改
    record.set('age',108);
    // 保存
    record.save();
})*/


// 根据主键查找,并修改 然后保存
// findByPk 根据逐渐查找
// Users.findByPk(14).then(user => {
//     if(user){
//         console.log(user.username)
//         user.set('username', 'lisi666');
//         user.save();
//     }else{
//         console.log('未找到用户')
//     }
// })

// 查找一条记录
/*Users.findOne({where: {username:'lisi'}}).then(user => {
    // user.destroy();
    console.log('user', user)
})*/

// 查找多条记录
/*Users.findAll({where: {username:'lisi'}}).then(users => {
    console.log('users', users.length)
})*/

// 汇总模糊查询
/*Users.findAndCountAll({
    where: {
        username: {
            [Op.like]: 'lisi%'
        }
    },
    offset: 2,
    limit: 2
}).then(result => {
    console.log(result.count);
    console.log(result.rows);
});*/

// 删除记录 destroy
/*Users.findOne({where: {username:'lisi'}}).then(user => {
    // user.destroy();
})*/


// 复合查询
/*Users.findAll({
    where: {
        id: {  // id 在11，12，13中 或者id大于20
            [Op.or]: [
                [11,12,13],
                { [Op.gte]: 20 }
            ]
        },
        username: { // username 包含 'i' 字符
            [Op.like]: '%i%'
        },
        age: { // 年龄大于10
           [Op.gte]: 10
        }
    },
    order: [
        ['age','desc']
    ],
    offset: 1,
    limit: 10
}).then(users => {

    users.forEach(v=>{
        console.log(v.username)
    })
})*/

// 计算总数
/*Users.count().then( count => {
    console.log('总条数-》', count)
})*/

// 查询并汇总
/*Users.findAndCountAll({
    where: {
        username: {
            [Op.like]: '%i%'
        }
    }
}).then(result => {
    console.log('result.count', result.count)
    console.log('result.rows', result.rows)
});*/

// 计算年龄的汇总
/*Users.sum('age').then( sum => {
    console.log('sum', sum)
})*/

// 获取年龄最大的用户
/*Users.max('age').then( user => {
    console.log('user', user)
})*/

// 获取年龄最小的用户
/*Users.min('age').then( user => {
    console.log('user', user)
})*/


// 关联查询 ==========
// BelongsTo   model1属于model2
// HasOne      model1 和 model2 是 1：1关系
// HasMany      model1 和 model2 是 1：m关系
// BelongsToMany  model1 和 model2 是 n：m关系

// 先弄一个数据表模型，在建立关联查询
const Message = sequelize.define('message', {
    id: {
        type: Sequelize.INTEGER(10),
        primaryKey: true,
        allowNull: false,
        autoIncrement: true
    },
    uid: { // 外键： 相当于 users表的id对应的主
        type: Sequelize.INTEGER(10),
        defaultValue: 0,
        references: {
            model:  Users, // 关联的外键表
            key: 'id' // 关联的字段
        }
    },
    content: {
        type: Sequelize.STRING(255),
        allowNull: true,
        defaultValue: ''
    }
}, {
    timestamps: false,
    freezeTableName: true, // 如果freezeTableName为true，则sequelize不会尝试更改模型名称以获取表名
    tableName: 'message'
})

// 关联查询案例1： 查询某个留言是谁的留下的 （查询messsage的同时 把user查出来）
// ① 在数据模型中用references 指定关联表和关联字段
// ② 建立关联关系
Message.belongsTo(Users, {
    foreignKey: 'uid'
})

// ③ 查询
Message.findByPk(4, {
    include: [Users]
}).then( msg => {
    console.log('id为:'+msg.get('id')+'，内容为:'+msg.get('content')+',所对应的留言人是:'+msg.User.get('username'))
})